<style lang="less">
  @import './split-pane.less';
</style>

<template>
  <div
    :class="wraperClasses"
    ref="wraper"
    @mouseup="handleMouseup"
    @mousemove="handleMousemove"
    @mouseleave="handleMouseout">
    <div v-if="direction === 'horizontal'" :class="`${prefix}-container`">
      <div :class="`${prefix}-left-area`" :style="{width: leftSize}">
        <slot name="left"></slot>
      </div>
      <slot name="trigger">
        <div
          :class="`${prefix}-trigger`"
          ref="trigger"
          :style="horizontalTriggerStyle"
          @mousedown="handleMousedown"
          unselectable="on">
          <div class="trigger-middle-point"><p></p>
            <p></p>
            <p></p>
            <p></p>
            <p></p>
            <p></p></div>
        </div>
      </slot>
      <div :class="`${prefix}-right-area`" :style="{width: rightSize}">
        <slot name="right"></slot>
      </div>
    </div>

    <div v-else :class="`${prefix}-container`">
      <div :class="`${prefix}-top-area`" :style="{height: leftSize}">
        <slot name="top"></slot>
      </div>
      <slot name="trigger">
        <div
          :class="`${prefix}-trigger`"
          ref="trigger"
          :style="verticalTriggerStyle"
          @mousedown="handleMousedown"
          unselectable="on">
          <div class="trigger-middle-point"><p></p>
            <p></p>
            <p></p>
            <p></p>
            <p></p>
            <p></p></div>
        </div>
      </slot>
      <div :class="`${prefix}-bottom-area`" :style="{height: rightSize}">
        <slot name="bottom"></slot>
      </div>
    </div>
  </div>
</template>

<script>
const oneOf = function (ele, targetArr) {
  if (targetArr.indexOf(ele) >= 0) {
    return true
  } else {
    return false
  }
}
export default {
  name: 'splitPane',
  props: {
    value: {
      type: [Number, String],
      default: 50
    },
    direction: {
      type: String,
      default: 'horizontal',
      validator (val) {
        return oneOf(val, ['vertical', 'horizontal'])
      }
    },
    min: {
      type: [Number, String],
      default: 3
    },
    max: {
      type: [Number, String],
      default: 97
    },
    maxRight: {
      type: Boolean,
      default: false
    },
    right: {
      type: Boolean,
      default: false
    },
    triggerStyle: {
      type: Object,
      default () {
        if (this.direction === 'horizontal') {
          return {
            width: '4px',
            background: '#BDBDBD'
          }
        } else {
          return {
            height: '4px',
            background: '#BDBDBD'
          }
        }
      }
    }
  },
  data () {
    return {
      prefix: 'split-pane',
      canMove: false,
      triggerOffset: 50,
      triggerOldOffset: 50,
      offset: {},
      atMin: false,
      atMax: false,
      directionMark: 0
    }
  },
  computed: {
    wraperClasses () {
      return [
        this.prefix,
        this.direction === 'vertical' ? `${this.prefix}-vertical` : `${this.prefix}-horizontal`
      ]
    },
    leftSize () {
      return this.right ? `${100 - this.triggerOffset}%` : `${this.triggerOffset}%`
    },
    rightSize () {
      return this.right ? `${this.triggerOffset}%` : `${100 - this.triggerOffset}%`
    },
    triggerLeft () {
      return this.right ? `${100 - this.triggerOffset}%` : `${this.triggerOffset}%`
    },
    minTransed () {
      return this.transValue(this.min)
    },
    maxTransed () {
      let max = this.right ? (100 - this.transValue(this.max)) : this.transValue(this.max)
      return this.maxRight ? 100 - max : max
    },
    horizontalTriggerStyle () {
      return Object.assign({left: this.triggerLeft}, this.triggerStyle)
    },
    verticalTriggerStyle () {
      return Object.assign({top: this.triggerLeft}, this.triggerStyle)
    }
  },
  methods: {
    handleMouseup (e) {
      this.canMove = false
      this.$emit('on-resizing-end', e)
    },
    transValue (val) {
      return (typeof val === 'number') ? val : Math.floor(((parseFloat(val) / this.$refs.wraper.offsetWidth) * 10000)) / 100
    },
    handleMousedown (e) {
      this.canMove = true
      this.triggerOldOffset = this.triggerOffset
      this.offset = {
        x: e.pageX,
        y: e.pageY
      }
      this.$emit('on-resizing-start', e)
      e.preventDefault()
    },
    handleMouseout () {
      this.canMove = false
    },
    handleMousemove (e) {
      if (this.canMove) {
        let offset
        let moveSize = 0
        if (this.direction === 'horizontal') {
          moveSize = Math.floor(((e.clientX - this.offset.x) / this.$refs.wraper.offsetWidth) * 10000) / 100
          offset = this.triggerOldOffset + (this.right ? -moveSize : moveSize)
        } else {
          moveSize = Math.floor(((e.clientY - this.offset.y) / this.$refs.wraper.offsetHeight) * 10000) / 100
          offset = this.triggerOldOffset + (this.right ? -moveSize : moveSize)
        }
        if (this.right) {
          let offsetHandle = 100 - offset
          if (offsetHandle <= this.minTransed) {
            this.triggerOffset = 100 - Math.max(offsetHandle, this.minTransed)
          } else {
            this.triggerOffset = 100 - Math.min(offsetHandle, this.maxTransed)
          }
        } else {
          if (offset <= this.minTransed) {
            this.triggerOffset = Math.max(offset, this.minTransed)
          } else {
            this.triggerOffset = Math.min(offset, this.maxTransed)
          }
        }
        e.atMin = (100 - offset) <= this.minTransed
        e.atMax = (100 - offset) >= this.maxTransed
        if (e.pageX > this.directionMark) {
          e.direction = 1
        } else {
          e.direction = 0
        }
        this.directionMark = e.pageX
        this.$emit('input', this.triggerOffset)
        this.$emit('on-resizing', e)
      }
    },
    setTriggerOffset (offset) {
      this.$nextTick(() => {
        this.triggerOffset = (typeof offset === 'number') ? offset : Math.floor(((parseInt(offset) / this.$refs.wraper.offsetWidth) * 10000)) / 100
        this.$emit('input', this.triggerOffset)
      })
    }
  },
  watch: {
    value (val) {
      this.$nextTick(() => {
        this.triggerOffset = (typeof val === 'number') ? val : Math.floor(((parseInt(val) / this.$refs.wraper.offsetWidth) * 10000)) / 100
      })
    }
  },
  mounted () {
    if (this.value !== undefined) {
      this.$nextTick(() => {
        this.triggerOffset = (typeof this.value === 'number') ? this.value : Math.floor(((parseInt(this.value) / this.$refs.wraper.offsetWidth) * 10000)) / 100
      })
      this.triggerOffset = (typeof this.value === 'number') ? this.value : Math.floor(((parseInt(this.value) / this.$refs.wraper.offsetWidth) * 10000)) / 100
    }
  }
}
</script>
